﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
using Andromeda.Forge.Common;
using Andromeda.Forge.DataSource.DB;
using Andromeda.Forge.Import.SqlServer;
using ForgeIt.Internal;
using ForgeIt.Properties;
using ForgeIt.Wizards;

namespace ForgeIt.Forms.Project.Datasource.DB
{
    /// <summary>
    /// 
    /// </summary>
    public partial class DatabaseProjectManager : BaseManager
    {
        /// <summary>
        /// 
        /// </summary>
        public DatabaseProjectManager(EnvDTE.Project project, Connect connector)
            : base(project, connector)
        {
            InEditMode = false;


            DataBind(new DataBaseConnectionModel
                         {
                             BaseNameSpace =
                                 !project.Name.ToLower().Contains(".dal") ? project.Name + ".Dal" : Project.Name,
                             DataSource =
                                 new DataBaseConnectionModel(FOSolution.Instance.ServerConnectionString).DataSource,
                             DataSourceKey = FOSolution.Instance.Name + "Db",
                             InitialCatalog = FOSolution.Instance.Name,
                             EnableMARS = true,
                             EnableTcpIp = false,
                             UserId = "sa",
                             UserPwd = "",
                             AdditionalFields = ""
                         }, FOSolution.Instance.DataSourceDBProjects);
        }

        /// <summary>
        /// 
        /// </summary>
        public DatabaseProjectManager()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 
        /// </summary>
        public DataBaseConnectionModel Record
        {
            get { return InternalRecord as DataBaseConnectionModel; }
            set { InternalRecord = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public FODataSourceDBProject FoProject { get; set; }


        /// <summary>
        /// 
        /// </summary>
        public bool InEditMode
        {
            get
            {
                return commitDataSourceButton.Enabled && dataSourceKeyTextBox.Enabled &&
                       userIdTextBox.Enabled && userPwdTextBox.Enabled && namespaceTextBox.Enabled &&
                       initialCatalogTextBox.Enabled && dataSourceTextBox.Enabled;
            }
            set
            {
                commitDataSourceButton.Enabled = value;
                dataSourceKeyTextBox.Enabled = value;
                userIdTextBox.Enabled = value;
                userPwdTextBox.Enabled = value;
                namespaceTextBox.Enabled = value;
                initialCatalogTextBox.Enabled = value;
                dataSourceTextBox.Enabled = value;
            }
        }


        private void commitDataSourceButton_Click(object sender, EventArgs e)
        {
            splitContainer1.Panel1.Enabled = false;
            splitContainer1.Panel2.Enabled = true;

            var model = (DataBaseConnectionModel) globalBindingSource.Current;

            backgroundWorker1.RunWorkerAsync(model);
        }

        /// <summary>
        /// 
        /// </summary>
        internal void DataBind(DataBaseConnectionModel model, FODataSourceDBProjectCollection projects)
        {
            SuspendLayout();

            Record = model;

            base.DataBind(Record);

            fODataSourceDBProjectBindingSource.DataSource = projects;
            fODataSourceDBProjectBindingSource.ResetBindings(false);

            InEditMode = true;

            ResumeLayout(true);
        }

        private void BackgroundWorker1DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                backgroundWorker1.ReportProgress(1,
                                                 new ReportProgressObject("Loading Table Information", 0, 0, 0, 0, null,
                                                                          0, 0));

                var model = (DataBaseConnectionModel) e.Argument;

                VwForgeTablesStub[] tables = VwForgeTablesStub.ListEntity(TableTypes.UserTable, model.ConnectionString);

                var groupedTables = new Dictionary<string, List<VwForgeTablesStub>>();
                foreach (VwForgeTablesStub table in tables)
                {
                    if (!groupedTables.ContainsKey(table.Table_Name))
                        groupedTables.Add(table.Table_Name, new List<VwForgeTablesStub>());
                    groupedTables[table.Table_Name].Add(table);
                }


                int totalTables = groupedTables.Count();
                int currentTableIndex = 0;
                backgroundWorker1.ReportProgress(2,
                                                 new ReportProgressObject(
                                                     "Loaded Table Information, proceeding with Views Information",
                                                     totalTables, 0, currentTableIndex, 0, null, 0, 0));
                VwForgeTablesStub[] views = VwForgeTablesStub.ListEntity(TableTypes.UserView,
                                                                         connectionStringTextBox.Text);
                var groupedViews = new Dictionary<string, List<VwForgeTablesStub>>();
                foreach (VwForgeTablesStub view in views)
                {
                    if (!groupedViews.ContainsKey(view.Table_Name))
                        groupedViews.Add(view.Table_Name, new List<VwForgeTablesStub>());
                    groupedViews[view.Table_Name].Add(view);
                }

                int totalViews = groupedViews.Count();
                int currentViewIndex = 0;
                backgroundWorker1.ReportProgress(3,
                                                 new ReportProgressObject(
                                                     "Loaded View Information, proceeding with Loading Tables",
                                                     totalTables, totalViews, currentTableIndex, currentViewIndex, null,
                                                     0, 0));

                var prj = new FODataSourceDBProject(FOSolution.Instance, dataSourceKeyTextBox.Text,
                                                    connectionStringTextBox.Text)
                              {
                                  BaseNameSpace = namespaceTextBox.Text,
                                  DatabaseEngineType = DatabaseEngineType.SqlServer
                              };


                foreach (var groupedTable in groupedTables)
                {
                    int currentColumnIndex = 0;
                    foreach (VwForgeTablesStub stub in groupedTable.Value)
                    {
                        backgroundWorker1.ReportProgress(currentTableIndex + 4,
                                                         new ReportProgressObject("Loading table column", totalTables,
                                                                                  totalViews, currentTableIndex,
                                                                                  currentViewIndex, stub,
                                                                                  groupedTable.Value.Count,
                                                                                  currentColumnIndex++));
                        FODataSourceDBProject.CreateColumnsFromDb(prj, TableTypes.UserTable, stub);
                    }
                    currentTableIndex++;
                }


                foreach (var groupedView in groupedViews)
                {
                    int currentColumnIndex = 0;
                    currentViewIndex++;
                    foreach (VwForgeTablesStub stub in groupedView.Value)
                    {
                        backgroundWorker1.ReportProgress(currentTableIndex + currentViewIndex + 4,
                                                         new ReportProgressObject("Loaded view column", totalTables,
                                                                                  totalViews, currentTableIndex,
                                                                                  currentViewIndex, stub,
                                                                                  groupedView.Value.Count,
                                                                                  currentColumnIndex++));
                        FODataSourceDBProject.CreateColumnsFromDb(prj, TableTypes.UserView, stub);
                    }
                }

                prj.ConsolidateExternalReferences();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + ex.StackTrace);
            }
        }

        private void BackgroundWorker1ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            var progressObject = (ReportProgressObject) e.UserState;

            if (progressObject.ItemCount > 0)
                progressBar1.Maximum = progressObject.ItemCount + 4;
            progressBar1.Value = e.ProgressPercentage;

            tablesToLoadTextBox.Text = progressObject.TableLoadingStatus;
            viewsToLoadTextBox.Text = progressObject.ViewLoadingStatus;

            if (!string.IsNullOrEmpty(progressObject.Message) && progressObject.Column == null)
            {
                progressLabel.Text = progressObject.Message;
            }
            if (progressObject.Column == null) return;

            currentTableTextBox.Text = progressObject.Column.Table_Name;
            currentColumnTextBox.Text = progressObject.Column.ColumnName;
            dataTypeTextBox.Text = progressObject.Column.ColumnTypeName;

            // ReSharper disable LocalizableElement
            columnsToLoadTextBox.Text = (progressObject.CurrentColumn + 1) + "/" + progressObject.TotalColumns;

            progressBar2.Maximum = progressObject.TotalColumns;
            progressBar2.Value = progressObject.CurrentColumn + 1;
            progressLabel.Text = "Loading Table: [" + progressObject.Column.Table_Name + "]/Column: [" +
                                 progressObject.Column.ColumnName + "] Data type: [" +
                                 progressObject.Column.ColumnTypeName + "]";
            // ReSharper restore LocalizableElement
        }

        private void BackgroundWorker1RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            splitContainer1.Panel2.Enabled = false;
            splitContainer1.Panel2.Enabled = true;
            DataBind(Record, FOSolution.Instance.DataSourceDBProjects);
            InEditMode = false;
            MessageBox.Show(Resources.Operation_Result_Label, Resources.Database_Added_Label);
            Close();
        }

        private void clearDataSourceButton_Click(object sender, EventArgs e)
        {
            DataBind(new DataBaseConnectionModel(), FOSolution.Instance.DataSourceDBProjects);
            InEditMode = false;
        }

        internal void DataBind(FODataSourceDBProject fODataSourceDBProject)
        {
            throw new NotImplementedException();
        }
    }
}